﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed
#pragma once

#include "GcmpSnapInterface.h"
#include "IObject.h"

namespace gcmp {

    class IDocument;
    class IPickFilter;
    class ISnapSettings;
    class IViewerContext;
    class Vector3d;
    class ISnapCandidatesPreprocessor;
    class IGraphicsPlane;
    class ICurve3d;
    class ILine3d;
    class IRemoteSnapFilter;
    class Coordinate3d;

    /// \brief 切点捕捉类型
    enum class TangencyPointSnapType : int32_t
    {
        StraightLine = 0,               ///< 直线
        Circle = 1,                     ///< 圆
        ArcBy3Pts = 2,                  ///< 三点圆弧
        ArcByTangentEndPoint = 3,       ///< 切线端点弧
        Ellipse = 4                     ///< 椭圆(弧)
    };

    /// \brief 捕捉输入对象，是捕捉的输入信息
    ///
    /// 包括视图信息、输入点、捕捉设置选项等
    FINAL_INTERFACE class GCMP_SNAP_INTERFACE_EXPORT ISnapContext : public IObject
    {
        DEFINE_CAST_DERIVED(gcmp::ISnapContext, gcmp::IObject);
    public:
        /// \brief 析构函数
        virtual ~ISnapContext() {};

        /// \brief 创建捕捉输入对象
        /// \return 返回创建的捕捉输入对象
        static OwnerPtr<ISnapContext> Create();

        /// \brief 克隆捕捉输入对象
        /// \return 返回克隆的捕捉输入对象
        virtual OwnerPtr<ISnapContext> Clone() const = 0;

        /// \brief 获取当前文档
        /// \return IDocument* 返回当前文档指针
        virtual IDocument* GetDocument() const = 0;

        /// \brief 设置当前文档
        /// \param pDocument 当前文档指针
        /// \return bool 成功返回true，失败返回false
        virtual bool SetDocument(IDocument* pDocument) = 0;

        /// \brief 获取捕捉设置信息
        ///        使用说明：在拿到捕捉设置做进一步的个性化配置后，需要调用SetSnapSettings，否则个性化配置不会生效
        /// \return 返回捕捉设置信息
        virtual OwnerPtr<ISnapSettings> GetSnapSettings() const = 0;

        /// \brief 设置捕捉设置信息
        /// \param pSnapSettings 捕捉设置信息
        /// \return bool 成功返回true，失败返回false
        virtual bool SetSnapSettings(const ISnapSettings* pSnapSettings) = 0;
        
        /// \brief 设置捕捉提示信息是否采用智能反背景色
        /// \param value true表示使用反背景色，反之
        /// \return bool 成功返回true，失败返回false
        virtual bool SetUseSmartAntiBackgroundColorForSnapPrompt(bool value) = 0;

        /// \brief 获取捕捉提示信息是否采用智能反背景色
        /// \return true表示使用反背景色，反之
        virtual bool UseSmartAntiBackgroundColorForSnapPrompt() const = 0;

        /// \brief 获取近程捕捉的拾取过滤器
        /// \return 近程捕捉的拾取过滤器指针
        virtual const IPickFilter* GetFilterForLocalSnap() const = 0;

        /// \brief 设置近程捕捉的拾取过滤器
        /// \param pFilterForLocalSnap 拾取过滤器
        /// \return 成功返回true，失败返回false
        virtual bool SetFilterForLocalSnap(const IPickFilter* pFilterForLocalSnap) = 0;

        /// \brief 获取近程捕捉大场景下的拾取容差
        /// \return 近程捕捉大场景下的拾取容差
        virtual double GetPickToleranceInLargeSceneForLocalSnap() const = 0;

        /// \brief 设置近程捕捉大场景下的拾取容差
        /// 
        /// \param tolerance 拾取容差值
        /// \return 成功返回true，失败返回false
        virtual bool SetPickToleranceInLargeSceneForLocalSnap(double tolerance) = 0;

        /// \brief 获取远程捕捉的拾取过滤器
        /// \return 返回远程捕捉的拾取过滤器指针
        virtual const IPickFilter* GetFilterForRemoteSnap() const = 0;

        /// \brief 设置远程捕捉的拾取过滤器
        /// \param pFilterForRemoteSnap 拾取过滤器
        /// \return 成功返回true，失败返回false
        virtual bool SetFilterForRemoteSnap(const IPickFilter* pFilterForRemoteSnap) = 0;

        /// \brief 获取远程捕捉的捕捉过滤器
        /// \return 返回远程捕捉的捕捉过滤器指针
        virtual const IRemoteSnapFilter* GetSnapFilterForRemoteSnap() const = 0;

        /// \brief 设置远程捕捉的捕捉过滤器
        /// \param pRemoteSnapFilter 捕捉过滤器
        /// \return 成功返回true，失败返回false
        virtual bool SetSnapFilterForRemoteSnap(const IRemoteSnapFilter* pRemoteSnapFilter) = 0;

        /// \brief 获取是否开启远程捕捉去重
        /// \return 返回是否开启远程捕捉去重
        virtual bool GetRemoveDuplicateRemoteSnaps() const = 0;

        /// \brief 设置是否开启远程捕捉去重
        /// \param value 设置值
        /// \return 成功返回true，失败返回false
        virtual bool SetRemoveDuplicateRemoteSnaps(bool value) = 0;

        /// \brief 获取当前视图信息
        /// \return 返回当前视图信息指针
        virtual const IViewerContext* GetViewerContext() const = 0;

        /// \brief 设置当前视图信息
        /// \param pViewerContext 当前视图信息
        /// \return 成功返回true，失败返回false
        virtual bool SetViewerContext(OwnerPtr<IViewerContext> pViewerContext) = 0;

        /// \brief 获取捕捉输入点
        ///
        /// 捕捉输入点用于捕捉求交，以捕捉输入点为基础，计算捕捉点，得到捕捉结果
        /// \return 返回捕捉输入点
        virtual const Vector3d& GetInputPoint() const = 0;

        /// \brief 设置捕捉输入点（如鼠标点）
        /// \param inputPoint 捕捉输入点
        /// \return 成功返回true，失败返回false
        virtual bool SetInputPoint(const Vector3d& inputPoint) = 0;

        /// \brief 设置捕捉候选对象预处理器
        /// \param snapCandidatesPreprocessor 捕捉候选对象预处理器
        /// \return 成功返回true，失败返回false
        virtual bool SetSnapCandidatesPreprocessor(const ISnapCandidatesPreprocessor* snapCandidatesPreprocessor) = 0;

        /// \brief 获取捕捉候选对象预处理器
        ///
        /// \return 捕捉候选对象预处理器指针
        virtual ISnapCandidatesPreprocessor* GetSnapCandidatesPreprocessor() const = 0;

        /// \brief 获取第一个捕捉输入点
        ///
        /// 比如在进行平行或者垂直捕捉时，需要第一个捕捉输入点信息
        /// \return 第一个捕捉输入点
        virtual const Vector3d* GetFirstPoint() const = 0;

        /// \brief 设置第一个捕捉输入点。在捕捉第二点时有效
        /// \param pFirstPoint 第一个输入点
        /// \return 成功返回true，失败返回false
        virtual bool SetFirstPoint(const Vector3d* pFirstPoint) = 0;
        
        /// \brief 获取切点捕捉类型
        ///
        /// \return 切点捕捉类型
        virtual TangencyPointSnapType GetTangencyPointSnapType() const = 0;
        
        /// \brief 设置切点捕捉类型
        ///
        /// \param type 切点捕捉类型
        /// \return 成功返回true，失败返回false
        virtual bool SetTangencyPointSnapType(TangencyPointSnapType type) = 0;

        /// \brief 获取用于切点捕捉的多个辅助点
        ///
        /// \return 用于切点捕捉的多个辅助点
        virtual const std::vector<Vector3d>& GetAuxiliaryPoints() const = 0;

        /// \brief 设置用于切点捕捉的多个辅助点
        ///
        /// \param auxiliaryPoints 多个辅助点
        /// \return 成功返回true，失败返回false
        ///
        /// 示例：若当前绘制的是三点圆弧，则辅助点为三点圆弧的前两点
        ///       若当前绘制的是切线端点弧，则第一个辅助点为端点，第二个辅助点为切向
        virtual bool SetAuxiliaryPoints(const std::vector<Vector3d>& auxiliaryPoints) = 0;

        /// \brief 获取捕捉平面
        /// \return 捕捉平面
        virtual const IGraphicsPlane& GetSnapPlane() const = 0;

        /// \brief 设置捕捉平面
        /// \param snapPlane 捕捉平面
        /// \return 成功返回true，失败返回false
        virtual bool SetSnapPlane(const IGraphicsPlane& snapPlane) = 0;

        /// \brief 设置捕捉平面
        /// \param opSnapPlane 捕捉平面
        /// \return 成功返回true，失败返回false
        virtual bool SetSnapPlane(OwnerPtr<IGraphicsPlane> opSnapPlane) = 0;

        /// \brief  获取用于三维轴向非对象捕捉的坐标系
        /// \return 用于三维轴向非对象捕捉的坐标系
        virtual const Coordinate3d& GetCoordinate() const = 0;

        /// \brief 设置用于三维轴向非对象捕捉的坐标系
        /// \param coordinate3d 坐标系
        /// \return 设置成功返回true，否则返回false
        virtual bool SetCoordinate(const Coordinate3d & coordinate3d) = 0;

        /// \brief 设置捕捉方向是否由ModelView确定
        /// \param bool true表示捕捉方向由ModelView确定，false表示捕捉方向由捕捉平面(SnapPlaneType)确定
        /// \return 设置成功返回true，失败返回false
        virtual bool SetIsDirectionDeterminedByModelView(bool value) = 0;

        /// \brief 获取捕捉方向是由ModelView确定还是由捕捉平面确定的布尔值
        /// 
        /// \return true表示捕捉方向由ModelView确定，false表示捕捉方向由捕捉平面(SnapPlaneType)确定
        virtual bool IsDirectionDeterminedByModelView() const = 0;

        /// \brief 获取捕捉约束线，捕捉必须在约束线上
        /// \return 捕捉约束线
        virtual const ICurve3d* GetConstraintCurve() const = 0;

        /// \brief 设置捕捉约束线
        /// \param pConstraintCurve 捕捉约束线
        /// \return 成功返回true，失败返回false
        virtual bool SetConstraintCurve(const ICurve3d* pConstraintCurve) = 0;

        /// \brief 设置捕捉的几何辅助线,用于共线捕捉
        ///
        /// \param pComponentCurve 几何辅助线
        /// \return 成功返回true，失败返回false
        virtual bool SetCollinearCurve(const ICurve3d* pComponentCurve) = 0;

        /// \brief 获取几何辅助线,用于共线捕捉
        ///
        /// 默认为定位线
        /// \return 几何辅助线
        virtual const ICurve3d* GetCollinearCurve() const = 0;

        /// \brief 设置额外的一组Element参与捕捉
        /// \param 额外参与捕捉的一组Element的id集合
        /// \return 设置成功返回true，否则返回false
        virtual bool SetExtraElementsForSnap(const std::set<ElementId>& ids) = 0;

        /// \brief 获取额外参与捕捉的一组Element的id集合
        /// \return 额外参与捕捉的一组Element的id集合
        virtual const std::set<ElementId>& GetExtraElementsForSnap() const = 0;

        /// \brief 获取参照线线
        ///
        /// 参照线即：正在平移直线时，直线的垂线；拖拽直线夹点时，表示原始方向的直线
        /// \return 参照线
        virtual const ILine3d* GetReferenceLine() const = 0;

        /// \brief 移动元素时设置捕捉数据
        /// \param movingElements 当前移动的元素ElementId的集合
        /// \param originalPosition 原始位置
        /// \param firstPoint 是否为第一个点
        /// \param originalLine 是否为原始线
        /// \param constraintCurve 是否为约束线
        /// \return 成功返回true，失败返回false
        //移到utils
        virtual bool SetDataFromMovingElements(const std::vector<ElementId>& movingElements, const Vector3d& originalPosition, bool firstPoint = true, bool originalLine = true, bool constraintCurve = true) = 0;
    };
}// namespace gcmp

